// /*
// 尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
// 接受一个函数作为参数
// 当状态确定之后就不能在发生更改
// 当一个promise对象存在多个then调用时需要将调用方法依次存进数组，并在知道状态后执行
// 当then 存在链式调用时，返回一个
// 当then中存在异步操作的时候，将其存起来，方便以后按照状态进行调用
// 
// */
const PENDING = 'pending' //等待状态
const FULILLED = 'fulilled' //成功
const REJECTED = 'rejected' //失败
class MyPromise {

    constructor( exector ) {
        // exector是一个执行器 进入会立即执行
        //进入构造器时若有代码错误要报错误状态
        try {
            exector( this.resolve, this.reject )
        } catch ( error ) {
            this.reject( error )
        }
    }
    //默认等待状态
    status = PENDING
    //成功之后的值
    value = undefined
    //失败之后的原因
    reason = undefined

    //异步时需要存一个成功的回调方法
    // successfulCallBack = undefined
    //then多次调用时需要保存一个数组
    successfulCallBack = []
    //异步时需要存一个失败的回调方法
    // failedCallBack = undefined
    failedCallBack = []
    // 成功调用的方法 - 将状态更改
    resolve = ( value ) => {
        if ( this.status !== PENDING ) return
        this.status = FULILLED
        //将传进来的参数保存起来
        this.value = value
        //shift（）会更改数组长度 弹出的是一个方法，立即执行即可
        while ( this.successfulCallBack.length ) this.successfulCallBack.shift()()
    }
    //失败执行的方法
    reject = ( reason ) => {
        if ( this.status !== PENDING ) return
        this.status = REJECTED
        this.reason = reason
        //shift（）会更改数组长度 弹出的是一个方法，立即执行即可
        while ( this.failedCallBack.length ) this.failedCallBack.shift()()
    }

    then( successfulCallBack, failedCallBack ) {
        //then 变为可选参数，当传入的参数为空时，手动加上一个返回方法，将值传递到下个then中
        successfulCallBack = successfulCallBack ? successfulCallBack : value => value
        failedCallBack = failedCallBack ? failedCallBack : reason => { throw reason }
        let promise2 = new MyPromise( ( resolve, reject ) => {
            if ( this.status === FULILLED ) {
                //由于promise2此时还没有值，需要异步执行获取promise2
                setTimeout( () => {
                    try {
                        //将执行结果本地存起来，用于比较
                        let x = successfulCallBack( this.value )
                        JudgeReturnType( promise2, x, resolve, reject )
                    } catch ( error ) {
                        reject( error )
                    }
                }, 0 );
            }
            else if ( this.status === REJECTED ) {
                setTimeout( () => {
                    try {
                        //将执行结果本地存起来，用于比较
                        let x = failedCallBack( this.reason )
                        JudgeReturnType( promise2, x, resolve, reject )
                    } catch ( error ) {
                        reject( error )
                    }

                }, 0 );
            } else {
                //等待状态 - 缓存回调方法
                // this.successfulCallBack = successfulCallBack
                // this.failedCallBack = failedCallBack
                // 向successfulCallBack传入函数，如果then 这时是个异步操作，将操作存起来去执行
                this.successfulCallBack.push( () => {
                    setTimeout( () => {
                        try {
                            let x = successfulCallBack( this.value )
                            JudgeReturnType( promise2, x, resolve, reject )
                        } catch ( e ) {
                            reject( e )
                        }
                    }, 0 );
                } )
                this.failedCallBack.push( () => {
                    setTimeout( () => {
                        try {
                            let x = failedCallBack( this.reason )
                            JudgeReturnType( promise2, x, resolve, reject )
                        } catch ( e ) {
                            reject( e )
                        }
                    }, 0 );
                } )
            }
        } )
        return promise2
    }
    //all是类的静态方法
    static all( array ) {
        let result = []
        let index = 0
        return new Promise( ( resolve, reject ) => {
            let addData = ( key, value ) => {
                result[key] = value
                index++
                if ( index === array.length ) {
                    resolve( result )
                }
            }
            //对传递的数组进行遍历
            for ( let i = 0; i < array.length; i++ ) {
                let current = array[i];
                if ( current instanceof MyPromise ) {
                    //若是MyPromise对象就执行then，去添加值或者reject返回
                    current.then( value => addData( i, value ), reason => reject( reason ) )
                } else {
                    //普通值就直接添加
                    addData( i, array[i] )
                }
            }
        } )
    }

    catch( failedCallBack ) {
        //借助then,传入第二个参数
        return this.then( undefined, failedCallBack )
    }

    static resolve( value ) {
        if ( value instanceof MyPromise ) return value
        return new MyPromise( resolve => resolve( value ) )
    }
}
//promise2 判断是否循环
function JudgeReturnType( promise2, x, resolve, reject ) {
    //返回自己的话报错
    if ( promise2 === x ) {
        return reject( new TypeError( 'Chaining cycle detected for promise #<Promise>' ) )
    }
    if ( x instanceof MyPromise ) {
        //是一个MyPromise对象 根据状态去做事
        //    x.then(value=>resolve(value),reason=>reject(reason))
        x.then( resolve, reject )
    } else {
        //普通值
        resolve( x )
    }
}
module.exports = MyPromise